#pragma once

#include <WinSock2.h>
#include "Communication.h"
#include <unordered_map>

enum CacheDataStatus
{
	CDS_UNDEFINED,
	CDS_AVAILABLE,
	CDS_NOTAVAILABLE,
	CDS_PENDING
};

class CWSABufferInfo
{
public:
	LPWSABUF lpBuffers;
	DWORD dwBufferCount;
	DWORD uNumberOfBytesRecvd;
	WinsockHookType originalHookType; 
	INT nOperationResult;
};

class CSocketHelper
{
public:
	CSocketHelper(VOID);
	CSocketHelper(SOCKET s);
	CSocketHelper(CSocketHelper &helper);
	~CSocketHelper(void);

private:
	SOCKET m_socketRelated;
	INT m_isCacheDataAvailable;
	std::unordered_map<WSAEVENT, CWSABufferInfo*> mapEvent2WSABuffer;
	
public:
	BOOL m_bIsCSGTStarted;

	BOOL IsCacheDataAvailable(void);
	BOOL IsFollowingCacheDataAvailable(void);
	VOID SetRelatedSocket(SOCKET socket);
	INT GetCacheData(PUCHAR lpData, int nLength); // Winsock 1.0
	INT GetCacheData(LPWSABUF lpBuffers, DWORD nBufferCount); // Winsock 2.0
	CWSABufferInfo* RegisterWSAEvent(WSAEVENT uEvent, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, WinsockHookType originalHookType);
	BOOL RemoveWSAEvent(WSAEVENT uEvent);
	CWSABufferInfo* GetWSABufferFromEvent(WSAEVENT uEvent);
	VOID StartCacheStatusGuardingThread(HANDLE hEvent);
	static VOID threadCacheStatusGuard(PVOID param);
};

class CCacheStatusGuardInfo
{
public:
	CSocketHelper* pHelper;
	HANDLE hEvent;
};